from PIL import ImageTk
from service.PlusterLog import PlusterLog
from service.task import TaskM
from Tkinter import *
import Tix
from service.pconfig import PConfig
from service.exception import *
import time
class NodeListView(PlusterLog):
    def __init__(self,ctl,root):
        PlusterLog.__init__(self)
        self.ctl=ctl
        self.root=root
        self.start_time=time.ctime()
        CanvasH=1800# Hight of canvas
        CanvasW=900#Width of canvas
        self.icon_id=[] #keep icon id in canvas
        self.icon_temp=[] #keep temp reference for icon image
        self.rec_id=[] #keep rec id in convas
        self.node_info={}
        self.name_list=[]
        self.png_path=PConfig.attribute.rrd_path+"png/"
        self.old_node_list=[] #keep old list in order to remove nonexists nodes
        #ImageTk has a bug.We must keep a reference of every photo
        self.closeimg = ImageTk.PhotoImage(file="./form/close.jpg")
        #Create canvas and draw icon and node name on it
        self.iconCanvas=Canvas(self.root.Form1.SSTab1.page0,\
                               height=CanvasH,width=CanvasW,\
                               scrollregion=(0,0,CanvasW,CanvasH))
        # form this two var and x,y in event we know which icon is
        # pressed
        self.imgWidth=80#width of each img.
        self.imgHight=70#Hight of each img.
        nodeNameCount=1#for create name

        for i in range(25):
            for j in range(8):#number of nodes in each line
                item = self.iconCanvas.create_image\
                       (self.imgWidth*j, self.imgHight*i,\
                        anchor=NW, image=self.closeimg)

                text = self.iconCanvas.create_text\
                       (self.imgWidth*j+25,self.imgHight*i+60,\
                        text="cn"+str(nodeNameCount))
                nodeNameCount+=1

        #Create scrollbar and bind it with canvas
        self.bar=Scrollbar(self.root.Form1.SSTab1.page0)
        self.bar.pack(side="right",fill="y")
        self.iconCanvas['yscrollcommand']=(self.bar,'set')
        self.bar['command']=(self.iconCanvas,'yview')
        self.iconCanvas.pack(side="left",expand="yes")
        self.iconCanvas.bind("<Button-3>", self._OnRightClick )
        #Create popupMenu bind to canvas
        self.popout = Tix.PopupMenu(self.iconCanvas,\
                                    title="Task",spring=False, \
                                        postcmd=self.is_alive)

        self.popout.bind_widget(self.iconCanvas)

        #add new popout command here and add command function below
        #command func need to set self.currentTask and _OnRightClick
        #will help you find out the node and call controller for help

        self.popout.menu.add_command(label='SSH to Node',\
                                     underline=0,\
                                     command=self.setSSHTask)
        self.popout.menu.add_command(label='Node Info', underline=0,\
                                     command=self.setInfoTask)
    def is_alive (self,x,y):
        """Check node is alive """
        #Note, Don't use x,y here. _OnRightClick will set right node'
        return self.ctl.handle_request('check_alive',self.selectNode)

    def setSSHTask(self):
        task="SSH"
        self.log.debug("Select Node:%s Task is %s"%\
                       (self.selectNode,task))
        self.ctl.handle_request(task,self.selectNode)

    def setInfoTask(self):
        task="Info"
        self.log.debug("Select Node:%s Task is %s"%\
                       (self.selectNode,task))
        self.ctl.handle_request(task,self.selectNode)

    def _OnRightClick(self,event):
        """Check which node is pressed and set self.selectNode"""
        barx,bary=self.bar.get()
        xpos=event.x
        height=int(self.iconCanvas['height'])
        ypos=barx*height+event.y
        #self.log.debug("click at canvas x %d and y %d"%(xpos,ypos))
        self.selectNode=self._CordToNode(xpos,ypos)
        #elf.log.debug("nodeName,self.currentTask))

    def _CordToNode(self,x,y):
        """Convert x,y position to node name"""
        node=int(y/self.imgHight)*8+int(x/self.imgWidth)+1
        self.log.debug("_CordToNode %s"%str(node))
        return str(node)

    def _NodeToCord(self,num):
        """num is node bumber return x,y position"""
        y=int(num/8)*self.imgHight
        x=int((num-1)%8)*self.imgWidth
        return x,y

    def Update(self,doc):
        name_list=[]
        for id in self.icon_id:
            self.iconCanvas.delete(id)
        for id in self.rec_id:
            self.iconCanvas.delete(id)
        self.icon_id=[]
        self.icon_temp=[]
        self.rec_id=[]
        title= "%-15s%-55s%-25s%-26s%-26s\n"%("Node Name","CPU Type","Memory","IP Address","MAC")
        try:
            list=doc.get_node_list()
        except:
            self.log.error("Can not update node list.Check Nodelist Update.")
            raise
        for node in list:
            nodeName=node.get_host_name()
            name_list.append(nodeName)
            if not self.node_info.has_key(nodeName):
                ip=node.get_ip()
                mac=node.get_mac()
                cpu=node.cpu_type
                mem=node.total_mem
                text="%-15s%-45s%-25s%-26s%-26s\n"%(nodeName,cpu,mem,ip,mac)
                self.node_info[nodeName]=text
            icon_path=self.png_path+nodeName+"_ico.png"
            try:
                x,y=self._NodeToCord(int(nodeName))
            except:
                self.log.error("Can not conver node name to cord")
                raise
            icon_png=ImageTk.PhotoImage(file=icon_path)
            id=self.iconCanvas.create_image(x,y,anchor=NW,\
                                             image=icon_png)
            self.icon_id.append(id)
            r_id=self.iconCanvas.create_rectangle(x,y,x+49,y+48)
            self.rec_id.append(r_id)
            #We need to keep icon object. Becasue there's a bug in PIL
            self.icon_temp.append(icon_png)
            #del(icon_png)

        self.root.Form1.SSTab1.page1.Text1.text.delete(1.0,END)
        self.root.Form1.SSTab1.page1.Text1.text.insert(END,title)
        for t in self.node_info.values():
            self.root.Form1.SSTab1.page1.Text1.text.insert(END,t)
        for remove in [i for i in self.old_node_list if i not in name_list]:
            x,y=self._NodeToCord(int(remove))
            self.iconCanvas.create_image(x,y,anchor=NW,\
                                             image=self.closeimg)
        page2="""Pluster System Info

Total Node %d
Pluster Start Time %s"""%(len(name_list),self.start_time)
        self.root.Form1.SSTab1.page2.Text2.text.delete(1.0,END)
        self.root.Form1.SSTab1.page2.Text2.text.insert(END,page2)
        self.old_node_list=name_list



#self.log.debug(doc)
##        canv = self.root.Form1.SSTab1.page0.Shape1
##        if NodesDocument.nodesDoc==[]:
##            canv.itemconfigure(canv.item, fill='gray')
##        else:
##            canv.itemconfigure(canv.item, fill='green')

class NodeListAdapter:
    def __init__(self,doc):
        self.doc=doc
    def handle_request(self,task,node):
        print "nodeListAdapter handle %s on node %s"%(task,node)
        if task=="Info":
            node=self.doc.get_node(node)
            task=TaskM.manager.load_task(task)
            task.config(node)
            print "RUN INFO TASK.RUN"
            task.run()
        elif task=="SSH":
            node=self.doc.get_node(node)
            arg=node.get_ip()
            task=TaskM.manager.load_task(task)
            task.config(arg)
        elif task=="check_alive":
            try:
                node_doc=self.doc.get_node(node)
                if node_doc.is_alive():
                    return True
            except MainServerNoNodeError:
                return False



